package yuekao7.machine;

import com.alibaba.alink.operator.batch.BatchOperator;
import com.alibaba.alink.operator.batch.dataproc.SplitBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalMultiClassBatchOp;
import com.alibaba.alink.operator.batch.source.CsvSourceBatchOp;
import com.alibaba.alink.operator.common.evaluation.MultiClassMetrics;
import com.alibaba.alink.operator.common.evaluation.TuningBinaryClassMetric;
import com.alibaba.alink.pipeline.PipelineModel;
import com.alibaba.alink.pipeline.classification.DecisionTreeClassifier;
import com.alibaba.alink.pipeline.classification.LogisticRegression;
import com.alibaba.alink.pipeline.tuning.BinaryClassificationTuningEvaluator;
import com.alibaba.alink.pipeline.tuning.GridSearchCV;
import com.alibaba.alink.pipeline.tuning.ParamGrid;

public class Stockholders {
    public static void main(String[] args) throws Exception {
        //(1)	读取附件中的数据源，自定义划分训练集和测试集（3分）
        String filePath = "data/yk7/股票客户流失.csv";
        String schema
                //账户资金（元）	最后一次交易距今时间（天）	上月交易佣金（元）	累计交易佣金（元）	本券商使用时长（年）	是否流失
                //22686.5       ,297                    ,149.25             ,2029.85        ,0,                 0
                = "f0 double,f1 double,f2 double,f3 double,f4 int,label int";
        CsvSourceBatchOp csvSource = new CsvSourceBatchOp()
                .setFilePath(filePath)
                .setSchemaStr(schema)
                .setFieldDelimiter(",")
                .setIgnoreFirstLine(true)
                .setLenient(true)
                .setSkipBlankLine(true);
//        csvSource.print();
        String[] features =new String[]{"f0","f1","f2","f3","f4"};
        String label="label";

        BatchOperator<?> spliter = new SplitBatchOp().setFraction(0.8);
        BatchOperator<?> trainData = spliter.linkFrom(csvSource);
        BatchOperator<?> testData = spliter.getSideOutput(0);

        //(2)	自主选择使用Alink中至少两种算法构建模型，并设定初始值（7分）
        //逻辑回归
        LogisticRegression lr = new LogisticRegression()
                .setFeatureCols(features)
                .setLabelCol(label)
                .setPredictionCol("pred")
                .setPredictionDetailCol("pred_detail")
                .setNumThreads(1)
                .enableLazyPrintModelInfo();
        BatchOperator<?> lr_transform = lr.fit(trainData).transform(testData);

        //决策树分类器
        DecisionTreeClassifier dtc = new DecisionTreeClassifier()
                .setPredictionDetailCol("pred_detail")
                .setPredictionCol("pred")
                .setLabelCol(label)
                .setFeatureCols(features)
                .setMaxBins(128)
                .enableLazyPrintModelInfo();
        BatchOperator<?> dtc_transform = dtc.fit(trainData).transform(testData);
        //(3)	对以上算法参数进行调优，可以打印中间调优结果（7分）
        BinaryClassificationTuningEvaluator tuningEvaluator = new BinaryClassificationTuningEvaluator()
                .setLabelCol(label)
                .setPredictionDetailCol("pred_detail")
                .setTuningBinaryClassMetric(TuningBinaryClassMetric.ACCURACY);


        ParamGrid paramGrid1 = new ParamGrid()
                .addGrid(lr, LogisticRegression.L_1, new Double[] {1.0, 0.99, 0.98})
                .addGrid(lr, LogisticRegression.MAX_ITER, new Integer[] {3, 6, 9});

        GridSearchCV cv1 = new GridSearchCV()
                .setEstimator(lr)
                .setParamGrid(paramGrid1)
                .setTuningEvaluator(tuningEvaluator)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo("TrainInfo");
        PipelineModel lr_bestPipelineModel = cv1.fit(trainData).getBestPipelineModel();
        BatchOperator<?> lr_transform1 = lr_bestPipelineModel.transform(testData);

        ParamGrid paramGrid2 = new ParamGrid()
                .addGrid(dtc, DecisionTreeClassifier.MAX_DEPTH, new Integer[] {1, 2, 3})
                .addGrid(dtc, DecisionTreeClassifier.MAX_BINS, new Integer[] {3, 6, 9});

        GridSearchCV cv2 = new GridSearchCV()
                .setEstimator(dtc)
                .setParamGrid(paramGrid2)
                .setTuningEvaluator(tuningEvaluator)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo("TrainInfo");

        PipelineModel dtc_bestPipelineModel = cv2.fit(trainData).getBestPipelineModel();
        BatchOperator<?> dtc_transform1 = dtc_bestPipelineModel.transform(testData);
        //(4)	自主选择Alink至少两种指标进行模型评估（3分）
        MultiClassMetrics metrics1 = new EvalMultiClassBatchOp()
                .setLabelCol("label")
                .setPredictionDetailCol("pred_detail")
                .linkFrom(lr_transform1)
                .collectMetrics();
        System.out.println(metrics1.getAccuracy());
        System.out.println(metrics1.getMacroRecall());

        MultiClassMetrics metrics2 = new EvalMultiClassBatchOp()
                .setLabelCol("label")
                .setPredictionDetailCol("pred_detail")
                .linkFrom(dtc_transform1)
                .collectMetrics();

        System.out.println(metrics2.getAccuracy());
        System.out.println(metrics2.getMacroRecall());
    }
}
